import requests
import json
import base64
import urllib.parse
from django.shortcuts import render, redirect
from django.http import JsonResponse, StreamingHttpResponse, HttpRequest, HttpResponse,HttpResponseRedirect
from django.core.paginator import Paginator
from django.views.decorators.csrf import csrf_exempt
from django.contrib import messages
from urllib.parse import quote

username = 'admin'
def index(request: HttpRequest):
    return render(request, 'index.html', {'username': username})

# 获取 token，保存在 django_session 表中，方便每次访问 API 携带 token
def get_token(username, password):
    data = {
        "auth": {
            "identity": {
                "methods": [
                    "password"
                ],
                "password": {
                    "user": {
                        "domain": {
                            "name": "default"
                        },
                        "name": username,
                        "password": password
                    }
                }
            },
            "scope": {
                "project": {
                    "domain": {
                        "name": "default"
                    },
                    "name": username
                }
            }
        }
    }
    url = "http://192.168.88.128:5000/v3/auth/tokens"
    response = requests.post(url, data=json.dumps(data), headers={'Content-Type': 'application/json'})
    if response.status_code == 201:
        token = response.headers.get("X-Subject-Token")
        print(f"Token obtained successfully: {token}")
        return response
    else:
        print(f"Failed to get token: {response.status_code}, {response.text}")
        return None

def login(request: HttpRequest):
    if request.method == "POST":
        username = request.POST.get("username")
        passwd = request.POST.get("passwd")
        code = get_token(username, passwd)
        if code and code.status_code == 201:
            request.session['user'] = username     # 如果验证成功，将 token 保存在 session 中
            request.session['token'] = code.headers.get("X-Subject-Token")
            username = username
            return redirect('/index')
        else:
            error_msg = "用户名或密码不正确，请重新登录"
            return render(request, "login.html", {
                'login_error_msg': error_msg,
            })
    else:
        return render(request, "login.html")

# 登录成功后，读取容器 containers 并分页显示在 main.html 中
def containers(request):
    token = request.session.get('token')
    if not token:
        return HttpResponse("Token not found in session", status=401)

    headers = {'X-Auth-Token': token}
    url2 = "http://192.168.88.128:8080/v1/AUTH_c77bc692ae264ae698330fa0c402c30a?format=json"
    resp1 = requests.get(url2, headers=headers)
    if resp1.status_code != 200:
        print(f"Request failed with status code: {resp1.status_code}, Response: {resp1.text}")
        return HttpResponse(f"请求失败，状态码: {resp1.status_code}")
    try:
        resp2 = resp1.json()
    except ValueError as e:
        return HttpResponse(f"JSON 解析错误: {str(e)}")

    # 获取搜索关键词
    search_query = request.GET.get('search', '')
    if search_query:
        filtered_containers = [container for container in resp2 if search_query.lower() in container['name'].lower()]
        if not filtered_containers:
            # 搜索结果为空，设置提示信息
            messages.error(request, "没有找到该容器")
            search_query = ''  # 清除搜索关键词，重新加载完整列表
        else:
            resp2 = filtered_containers

    pages = Paginator(resp2, 7)
    try:
        page_number = request.GET['page']
    except:
        page_number = 1
    page = pages.get_page(page_number)

    # 将 resp2 转换为 JSON 字符串
    resp2_json = json.dumps(list(page.object_list))
    return render(request, 'containers.html', {'resp1': resp2_json})
def objects(request, data2):
    token = request.session.get('token')
    if not token:
        return HttpResponse("Token not found in session", status=401)
    headers = {'X-Auth-Token': token}
    url4 = f"http://192.168.88.128:8080/v1/AUTH_c77bc692ae264ae698330fa0c402c30a/{data2}?format=json"
    resp3 = requests.get(url4, headers=headers)
    if resp3.status_code != 200:
        print(f"Request failed with status code: {resp3.status_code}, Response: {resp3.text}")
        return HttpResponse(f"请求失败，状态码: {resp3.status_code}")
    try:
        resp4 = resp3.json()
    except ValueError as e:
        return HttpResponse(f"JSON 解析错误: {str(e)}")

    pages = Paginator(resp4, 6)
    try:
        page_number = request.GET['page']
    except:
        page_number = 1
    page = pages.get_page(page_number)

    # 将 resp2 转换为 JSON 字符串
    resp2_json = json.dumps(list(page.object_list))

    return render(request, 'objects.html', {'resp1': resp2_json, 'data2': data2})

# 查看对象内容

def showObjectContent(request: HttpRequest, container, object, objectname, content_type):
    print('-------查看对象')
    headers = {'X-Auth-Token': request.session.get('token')}
    url5 = f"http://192.168.88.128:8080/v1/AUTH_c77bc692ae264ae698330fa0c402c30a/{container}/{object}"
    resp3 = requests.get(url5, headers=headers)

    if resp3.status_code != 200:
        return HttpResponse(f"请求失败，状态码: {resp3.status_code}")

    # 尝试根据 Content-Type 获取字符集
    content_type_header = resp3.headers.get('Content-Type', '')
    charset = 'utf-8'  # 默认使用 UTF-8
    if 'charset=' in content_type_header:
        charset = content_type_header.split('charset=')[-1]

    if content_type_header.startswith('image/') or content_type_header.startswith('video/') or content_type_header.startswith('audio/'):
        # 如果是图片、视频或音频，直接返回二进制数据
        return HttpResponse(resp3.content, content_type=content_type_header)

    try:
        # 尝试根据 Content-Type 判断是否为 Base64 编码
        if 'base64' in content_type_header:
            content_bytes = resp3.content
            missing_padding = 4 - len(content_bytes) % 4
            if missing_padding:
                content_bytes += b'=' * missing_padding
            decoded_content = base64.b64decode(content_bytes)
            resp4 = decoded_content.decode(charset, errors='replace')
            is_base64 = True
        else:
            resp4 = resp3.content.decode(charset, errors='replace')
            is_base64 = False
    except (base64.binascii.Error, UnicodeDecodeError):
        resp4 = resp3.content.decode(charset, errors='replace')
        is_base64 = False

    if objectname.startswith('image'):
        return HttpResponse(resp3.content, content_type=content_type_header)
    elif objectname.startswith('video'):
        return HttpResponse(resp3.content, content_type=content_type_header)
    elif objectname.startswith('audio'):
        return HttpResponse(resp3.content, content_type=content_type_header)
    else:
        return HttpResponse(resp4, content_type='text/plain; charset=utf-8')


#下载对象文件
def downloadindex(request: HttpRequest, container, object):
    url = f"http://192.168.88.128:8080/v1/AUTH_c77bc692ae264ae698330fa0c402c30a/{container}/{object}"
    headers = {"X-Auth-Token": request.session['token']}
    datas = requests.get(url, headers=headers)
    if datas.status_code != 200:
        return HttpResponse(f"请求失败，状态码: {datas.status_code}", status=datas.status_code)

    response = StreamingHttpResponse(datas.iter_content(chunk_size=8192),
                                     content_type=datas.headers.get('Content-Type', 'application/octet-stream'))
    encoded_filename = urllib.parse.quote(object)
    response['Content-Disposition'] = f'attachment; filename="{encoded_filename}"'
    return response

#删除对象
def delObject(request, container, delobject):
    print('-------删除对象')
    headers = {}
    headers['X-Auth-Token'] = request.session['token']
    url5 = "http://192.168.88.128:8080/v1/AUTH_c77bc692ae264ae698330fa0c402c30a/" +container + "/" + delobject + "?format=json"
    requests.delete(url5, headers=headers)
    return redirect('/objects/'+container)
# 上传文件 添加对象

@csrf_exempt  # 使用此装饰器
def uploadindex(request, upload_object):
    if request.method == 'POST':
        # 检查是否有文件上传
        if 'file' not in request.FILES:
            messages.error(request, 'No file part')
            return redirect('/upload/{upload_object}')
            # return JsonResponse({'error': 'No file part'}, status=400)

        file = request.FILES['file']
        if file.name == '':
            messages.error(request, 'No selected file')
            return redirect(f'/upload/{upload_object}')
            # return JsonResponse({'error': 'No selected file'}, status=400)

        # 获取 token
        token = request.session.get('token')
        if not token:
            messages.error(request, 'Token not found in session')
            return redirect(f'/upload/{upload_object}')
            # return JsonResponse({'error': 'Token not found in session'}, status=401)

        # 配置 Swift 连接
        headers = {
            'X-Auth-Token': token,
            'Content-Type': file.content_type
        }

        # 构建上传 URL
        url = f"http://192.168.88.128:8080/v1/AUTH_c77bc692ae264ae698330fa0c402c30a/{upload_object}/{file.name}"

        try:
            # 上传文件到 Swift 容器
            response = requests.put(url, headers=headers, data=file)
            if response.status_code == 201:
                # 文件上传成功
                messages.success(request, '上传成功')
                return JsonResponse({'status': 'success', 'message': '文件上传成功'})
            else:
                # 返回错误信息
                messages.error(request, f"Failed to upload file: {response.status_code}, {response.text}")
                return JsonResponse({'status': 'error', 'message': f"Failed to upload file: {response.status_code}, {response.text}"}, status=response.status_code)
        except Exception as e:
            # 记录详细的错误信息
            import logging
            logger = logging.getLogger(__name__)
            logger.error(f"Error uploading file: {e}")
            return JsonResponse({'status': 'error', 'message': str(e)}, status=500)

    return render(request, 'upload.html', {'upload_object': upload_object})

# 创建容器
def addContainer(request,data):
    headers = {}
    headers['X-Auth-Token'] = request.session['token']
    url = f"http://192.168.88.128:8080/v1/AUTH_c77bc692ae264ae698330fa0c402c30a/"+str(data)+""
    requests.put(url, headers=headers)
    return redirect('/containers/')


# 删除容器
def delContainer(request, container):
    headers = {}
    headers['X-Auth-Token'] = request.session['token']
    url = f"http://192.168.88.128:8080/v1/AUTH_c77bc692ae264ae698330fa0c402c30a/{container}"
    try:
        response = requests.delete(url, headers=headers)
        if response.status_code == 204:
            # 成功删除容器
            messages.success(request, f"Container '{container}'删除成功")
            return redirect('/containers/')
        else:
            # 处理删除失败的情况
            return HttpResponse(f"Failed to delete container: {response.status_code} {response.text}",status=response.status_code)
    except requests.exceptions.RequestException as req_err:
         return HttpResponse(f"Request error: {str(req_err)}", status=500)
    except Exception as e:
         return HttpResponse(f"An unexpected error occurred: {str(e)}", status=500)


# 复制对象
def copyObject(request, source_container, source_object, target_container):
    print('-------复制对象')
    token = request.session.get('token')
    if not token:
        return HttpResponse("Token not found in session", status=401)

    # URL 编码路径部分
    encoded_source_container = quote(source_container)
    encoded_source_object = quote(source_object)
    encoded_target_container = quote(target_container)

    # 构建源对象路径
    source_path = f"/{encoded_source_container}/{encoded_source_object}"
    print(f"Encoded Source path: {source_path}")

    # 构建目标对象 URL
    url = f"http://192.168.88.128:8080/v1/AUTH_c77bc692ae264ae698330fa0c402c30a/{encoded_target_container}/{encoded_source_object}"
    print(f"Encoded Target URL: {url}")

    headers = {
        'X-Auth-Token': token,
        'X-Copy-From': source_path,
        'Content-Length': '0'
    }
    print(f"Headers: {headers}")

    try:
        response = requests.put(url, headers=headers)
        print(f"Copy response status code: {response.status_code}")
        print(f"Copy response headers: {response.headers}")
        print(f"Copy response text: {response.text}")

        if response.status_code == 201:
            messages.success(request, '复制成功')
            return redirect(f'/objects/{encoded_target_container}')
        else:
            messages.error(request, f"Failed to copy file: {response.status_code}, {response.headers}, {response.text}")
            return redirect(f'/objects/{encoded_source_container}')
    except requests.exceptions.RequestException as req_err:
        print(f"Request error: {str(req_err)}")
        return HttpResponse(f"Request error: {str(req_err)}", status=500)
    except Exception as e:
        print(f"An unexpected error occurred: {str(e)}")
        return HttpResponse(f"An unexpected error occurred: {str(e)}", status=500)




def testBody2_view(request):
    return render(request, 'containersBak.html')


def json_data_view(request):
    # 获取容器数据
    token = request.session.get('token')
    if not token:
        return JsonResponse({"code": 401, "msg": "Token not found in session"}, status=401)

    headers = {'X-Auth-Token': token}
    url2 = "http://192.168.88.128:8080/v1/AUTH_c77bc692ae264ae698330fa0c402c30a?format=json"
    resp1 = requests.get(url2, headers=headers)
    if resp1.status_code != 200:
        return JsonResponse({"code": resp1.status_code, "msg": resp1.text}, status=resp1.status_code)
    try:
        resp2 = resp1.json()
    except ValueError as e:
        return JsonResponse({"code": 500, "msg": f"JSON 解析错误: {str(e)}"}, status=500)

    # 获取搜索关键词
    search_query = request.GET.get('search', '')
    if search_query:
        filtered_containers = [container for container in resp2 if search_query.lower() in container['name'].lower()]
        resp2 = filtered_containers

    # 分页
    paginator = Paginator(resp2, 7)  # 每页显示 7 条数据
    page_number = request.GET.get('page', 1)
    page_obj = paginator.get_page(page_number)

    # 构造返回的 JSON 数据
    data = {
        "code": 0,
        "msg": "",
        "count": paginator.count,
        "data": list(page_obj)
    }

    return JsonResponse(data)











